/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
 * Description: udk mempool_ring source file
 * Author: -
 * Create: 2021.07.06
 */
#include <stdint.h>
#include <errno.h>

#include "securec.h"
#include "udk_common.h"
#include "udk_mempool.h"
#include "udk_ring.h"

static int udk_common_ring_mp_enqueue(struct udk_mempool *mp, void * const *obj_table, uint32_t n)
{
    return udk_ring_mp_enqueue_bulk(mp->pool_data, obj_table, n, NULL) == 0 ? -ENOBUFS : 0;
}

static int udk_common_ring_sp_enqueue(struct udk_mempool *mp, void * const *obj_table, uint32_t n)
{
    return udk_ring_sp_enqueue_bulk(mp->pool_data, obj_table, n, NULL) == 0 ? -ENOBUFS : 0;
}

static int udk_common_ring_mc_dequeue(struct udk_mempool *mp, void **obj_table, uint32_t n)
{
    return udk_ring_mc_dequeue_bulk(mp->pool_data, obj_table, n, NULL) == 0 ? -ENOBUFS : 0;
}

static int udk_common_ring_sc_dequeue(struct udk_mempool *mp, void **obj_table, uint32_t n)
{
    return udk_ring_sc_dequeue_bulk(mp->pool_data, obj_table, n, NULL) == 0 ? -ENOBUFS : 0;
}

static uint32_t udk_common_ring_get_count(const struct udk_mempool *mp)
{
    return udk_ring_count(mp->pool_data);
}

static int udk_common_ring_alloc(struct udk_mempool *mp)
{
    uint32_t rg_flags = 0;
    int ret;
    char rg_name[UDK_RING_NAMESIZE];
    struct udk_ring *r = NULL;

    ret = snprintf_s(rg_name, sizeof(rg_name), sizeof(rg_name) - 1, UDK_MEMPOOL_MZ_FORMAT, mp->name);
    if ((ret < 0) || (ret >= (int)sizeof(rg_name))) {
        return -ENAMETOOLONG;
    }

    /* ring flags */
    if (mp->flags & UDK_MEMPOOL_F_SP_PUT) {
        rg_flags |= RING_F_SP_ENQ;
    }
    if (mp->flags & UDK_MEMPOOL_F_SC_GET) {
        rg_flags |= RING_F_SC_DEQ;
    }
    if (mp->flags & UDK_MEMPOOL_F_LOCK) {
        rg_flags |= RING_F_LOCK;
    }

    /* Allocate the ring that will be used to store objects. */
    r = udk_ring_create(rg_name, udk_align32pow2(mp->size + 1), mp->socket_id, rg_flags);
    if (r == NULL) {
        return -ENOMEM;
    }

    mp->pool_data = r;

    return 0;
}

static void udk_common_ring_free(struct udk_mempool *mp)
{
    udk_ring_free(mp->pool_data);
    return;
}

static const struct udk_mempool_ops g_ops_mp_mc = {
    .name = "ring_mp_mc",
    .alloc = udk_common_ring_alloc,
    .free = udk_common_ring_free,
    .enqueue = udk_common_ring_mp_enqueue,
    .dequeue = udk_common_ring_mc_dequeue,
    .get_count = udk_common_ring_get_count,
};

static const struct udk_mempool_ops g_ops_sp_sc = {
    .name = "ring_sp_sc",
    .alloc = udk_common_ring_alloc,
    .free = udk_common_ring_free,
    .enqueue = udk_common_ring_sp_enqueue,
    .dequeue = udk_common_ring_sc_dequeue,
    .get_count = udk_common_ring_get_count,
};

static const struct udk_mempool_ops g_ops_mp_sc = {
    .name = "ring_mp_sc",
    .alloc = udk_common_ring_alloc,
    .free = udk_common_ring_free,
    .enqueue = udk_common_ring_mp_enqueue,
    .dequeue = udk_common_ring_sc_dequeue,
    .get_count = udk_common_ring_get_count,
};

static const struct udk_mempool_ops g_ops_sp_mc = {
    .name = "ring_sp_mc",
    .alloc = udk_common_ring_alloc,
    .free = udk_common_ring_free,
    .enqueue = udk_common_ring_sp_enqueue,
    .dequeue = udk_common_ring_mc_dequeue,
    .get_count = udk_common_ring_get_count,
};

UDK_MEMPOOL_REGISTER_OPS(g_ops_mp_mc);
UDK_MEMPOOL_REGISTER_OPS(g_ops_sp_sc);
UDK_MEMPOOL_REGISTER_OPS(g_ops_mp_sc);
UDK_MEMPOOL_REGISTER_OPS(g_ops_sp_mc);
